package cn.iocoder.yudao.module.def.service.common;


import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.def.dal.mysql.project.ProjectMapper;
import cn.iocoder.yudao.module.def.service.equipmentinfo.EquipmentInfoService;
import cn.iocoder.yudao.module.def.utils.CoordinateTransformUtil;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Stopwatch;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;

import javax.annotation.Resource;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.Duration;
import java.time.LocalDate;
import java.util.*;
import java.util.regex.Pattern;

@Service
@AllArgsConstructor
@Slf4j
public class DefCommonService {

    private final ProjectMapper projectMapper;

    private final AdminUserMapper userMapper;

    private final DeptService deptService;

    private final  StringRedisTemplate stringRedisTemplate;

    private final ObjectMapper objectMapper = new ObjectMapper();

    private final EquipmentInfoService equipmentInfoService;

    /**
     * 获取竣工年份列表
     *     code_txt: "2025",
     *     code_id: "2025",
     */
    public List<Map<String, Object>> getCompletedYearList() {
        List<Map<String, Object>> list = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            Map<String, Object> map = new HashMap<>();
            LocalDate now = LocalDate.now();
            int nowYear = now.getYear();
            map.put("code_txt", nowYear - i);
            map.put("code_id", nowYear - i);
            map.put("text", "年");
            map.put("label", "=");
            if (i == 4) {
                map.put("code_txt", nowYear - i + "年及以前");
                map.put("code_id", nowYear - i + "年及以前");
                map.put("text", "年及以前");
                map.put("label", "<=");
            }
            list.add(map);

        }
        return list;
    }

    public List<Map<String, Object>> getProjectCate() {
        return projectMapper.getProjectCate(null);
    }


    public List<Map<String, Object>> selectProjectsIndex(String projectCate, String finishDate, String keyword,
                                                         String sydw, String jsqy, String jsdw) {
        StopWatch stopwatch =new StopWatch();
        stopwatch.start();
        // 1. 生成缓存键
        String cacheKey = generateCacheKey(projectCate, finishDate, keyword, sydw, jsqy, jsdw);

        // 2. 尝试从缓存中获取数据
        try {
            String cachedData = stringRedisTemplate.opsForValue().get(cacheKey);
            if (StringUtils.isNotBlank(cachedData)) {
                // 缓存命中，反序列化并返回
                JavaType listType = objectMapper.getTypeFactory().constructCollectionType(List.class, Map.class);
                stopwatch.stop();
                log.info("缓存耗时：" + stopwatch.getTotalTimeMillis() + "毫秒");
                return objectMapper.readValue(cachedData, listType);
            }
        } catch (Exception e) {
            log.error("从缓存获取数据失败", e);
        }
        List<Map<String, Object>> list = fetchOriginalData(projectCate, finishDate, keyword, sydw, jsqy, jsdw);
        List<Map<String, Object>> equipmentIndexList = getEquipmentIndex(projectCate, finishDate, keyword, sydw, jsqy, jsdw);
        stopwatch.stop();
        log.info("查询耗时：" + stopwatch.getTotalTimeMillis() + "毫秒");
        stopwatch.start();
        // 处理经纬度转换和日期转换
        for (Map<String, Object> map : list) {
            // 经纬度转换
            Object lngLatObj = map.get("lng_lat");
            if (ObjectUtils.isNotEmpty(lngLatObj)) {
                try {
                    String bd09 = CoordinateTransformUtil.parseAndConvertToBd09(lngLatObj.toString());
                    if (StringUtils.isNotBlank(bd09)) {
                        String[] latLng = bd09.split(";");
                        if (latLng.length > 0) {
                            map.put("lng_lat", latLng[0]); // 更新为第一个经纬度点
                            map.put("lng_lat_str", bd09);
                        }
                    }
                } catch (Exception e) {
                    // 捕获异常并记录日志
                    System.err.println("经纬度转换失败: " + e.getMessage());
                }
            }

            // 将 invest_year 转换为 Date 对象
            Object beginDateStr = map.get("invest_year");
            map.put("invest_year", beginDateStr); // 替换为 Date 对象
        }

        // 按照 lng_lat 分组，并保留 begin_date 最新的记录
        Map<String, Map<String, Object>> groupedByLatLng = new LinkedHashMap<>();
        for (Map<String, Object> map : list) {
            Object lngLatObj = map.get("lng_lat");
            Object beginDateObj = map.get("invest_year");
            map.put("conditionType",1);
            if (ObjectUtils.isEmpty(lngLatObj) || ObjectUtils.isEmpty(beginDateObj)) {
                continue; // 跳过空值
            }

            String lngLat = lngLatObj.toString();

            int i = Integer.parseInt(beginDateObj.toString());
            // 如果当前分组中没有该经纬度，或者当前记录的 begin_date 更新，则更新分组
            if (!groupedByLatLng.containsKey(lngLat) ||
                    (groupedByLatLng.containsKey(lngLat) &&
                            i > Integer.parseInt(groupedByLatLng.get(lngLat).get("invest_year").toString()))) {
                groupedByLatLng.put(lngLat, map);
            }
        }
        List<Map<String, Object>> resultList = new ArrayList<>(groupedByLatLng.values());
        resultList.addAll(equipmentIndexList);
        stopwatch.stop();
        log.info("分组耗时：" + stopwatch.getTotalTimeMillis() + "毫秒");
        // 4. 将结果存入缓存 (设置过期时间，例如 10 分钟)
        try {
            String jsonData = objectMapper.writeValueAsString(resultList);
            stringRedisTemplate.opsForValue().set(cacheKey, jsonData, Duration.ofMinutes(60));
        } catch (Exception e) {
            log.error("将数据存入缓存失败", e);
        }
        // 返回去重后的结果
        return resultList;
    }

    /**
     * 根据参数生成缓存键
     * @param projectCate
     * @param finishDate
     * @param keyword
     * @param sydw
     * @param jsqy
     * @param jsdw
     * @return 缓存键
     */
    private String generateCacheKey(String projectCate, String finishDate, String keyword,
                                    String sydw, String jsqy, String jsdw) {
        // 可以使用更复杂的算法生成键，例如 MD5
       return  generateCacheKeyWithMD5(projectCate, finishDate, keyword, sydw, jsqy, jsdw);
    }

    /**
     * 使用 MD5 算法生成缓存键
     *
     * @param projectCate 项目类别
     * @param finishDate  完工日期
     * @param keyword     关键词
     * @param sydw        使用单位
     * @param jsqy        建设区域
     * @param jsdw        建设单位
     * @return MD5 摘要作为缓存键
     */
    private String generateCacheKeyWithMD5(String projectCate, String finishDate, String keyword,
                                           String sydw, String jsqy, String jsdw) {
        try {
            // 构造原始键字符串
            StringBuilder rawKeyBuilder = new StringBuilder("project_index:");
            rawKeyBuilder.append(projectCate != null ? projectCate : "")
                    .append(":")
                    .append(finishDate != null ? finishDate : "")
                    .append(":")
                    .append(keyword != null ? keyword : "")
                    .append(":")
                    .append(sydw != null ? sydw : "")
                    .append(":")
                    .append(jsqy != null ? jsqy : "")
                    .append(":")
                    .append(jsdw != null ? jsdw : "");

            String rawKey = rawKeyBuilder.toString();

            // 创建 MessageDigest 实例并计算 MD5
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] digest = md.digest(rawKey.getBytes());

            // 将字节数组转换为十六进制字符串
            StringBuilder hexString = new StringBuilder();
            for (byte b : digest) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            return "project_index_md5:" + hexString; // 添加前缀便于识别
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("无法生成 MD5 摘要", e);
        }
    }
    private List<Map<String, Object>> fetchOriginalData(String projectCate, String finishDate, String keyword,
                                                        String sydw, String jsqy, String jsdw) {
        // 原始查询逻辑
        String[] projectCates = StringUtils.isNotBlank(projectCate) ? projectCate.split(",") : null;
        String[] sydws = StringUtils.isNotBlank(sydw) ? sydw.split(",") : null;
        String[] jsqys = StringUtils.isNotBlank(jsqy) ? jsqy.split(",") : null;
        String[] jsdws = StringUtils.isNotBlank(jsdw) ? jsdw.split(",") : null;
        String[] jsqyArea = null;
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        assert loginUser != null;
        AdminUserDO adminUserDO = userMapper.selectById(loginUser.getId());
        DeptDO dept = deptService.getDept(adminUserDO.getDeptId());
        if (!Objects.equals(dept.getName(), "浙江省") && StringUtils.isNotBlank(jsqy) && !dept.getName().contains("市")) {
            jsqyArea = jsqys;
            jsqys = null;
        }

//        List<YearCondition> processedYears = processFinishDate(finishDate);
//        List<String> processedYears = StringUtils.isNotBlank(finishDate) ? Arrays.stream(finishDate.split(",")).collect(Collectors.toList()) : null;
        String startYear = null;
        String endYear = null;
        if (StringUtils.isNotBlank(finishDate)) {
            String[] yearParts = finishDate.split(",");
            startYear = yearParts[0];
            endYear = yearParts.length > 1 ? yearParts[1] : null;
        }

        return projectMapper.selectProjectsIndex(projectCates, null, keyword, sydws, jsqys, jsdws, startYear, endYear, jsqyArea);
    }

    public List<Map<String, Object>> getEquipmentIndex(String projectCate, String finishDate, String keyword,
                                                        String sydw, String jsqy, String jsdw) {

        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        assert loginUser != null;
        AdminUserDO adminUserDO = userMapper.selectById(loginUser.getId());
        DeptDO dept = deptService.getDept(adminUserDO.getDeptId());
        if (!Objects.equals(dept.getName(), "浙江省")){
            return Collections.EMPTY_LIST;
        }
        // 原始查询逻辑
        String[] projectCates = StringUtils.isNotBlank(projectCate) ? projectCate.split(",") : null;
        String[] sydws = StringUtils.isNotBlank(sydw) ? sydw.split(",") : null;
        String[] jsqys = StringUtils.isNotBlank(jsqy) ? jsqy.split(",") : null;
        String[] jsdws = StringUtils.isNotBlank(jsdw) ? jsdw.split(",") : null;
        String[] jsqyArea = null;

        if (!Objects.equals(dept.getName(), "浙江省") && StringUtils.isNotBlank(jsqy) && !dept.getName().contains("市")) {
            jsqyArea = jsqys;
            jsqys = null;
        }

        String startYear = null;
        String endYear = null;
        if (StringUtils.isNotBlank(finishDate)) {
            String[] yearParts = finishDate.split(",");
            startYear = yearParts[0];
            endYear = yearParts.length > 1 ? yearParts[1] : null;
        }
        return equipmentInfoService.getEquipmentIndex(projectCates, keyword, sydws, jsqys, jsdws, startYear, endYear, jsqyArea);
    }


    private List<YearCondition> processFinishDate(String finishDate) {
        List<YearCondition> processedYears = new ArrayList<>();
        if (finishDate != null && !finishDate.isEmpty()) {
            String[] yearParts = finishDate.split(",");
            for (String part : yearParts) {
                if (Pattern.matches("^[0-9]{4}$", part)) {
                    processedYears.add(new YearCondition(part, false));
                } else if (Pattern.matches("^[0-9]{4}及以前$", part)) {
                    String year = part.replaceAll("及以前", "");
                    processedYears.add(new YearCondition(year, true));
                }
            }
        }
        return processedYears;
    }

    public Map<String, Object> getInfo(Integer id) {
        Map<String, Object> map = projectMapper.selectByDataId(id);
        Object lngLatObj = map.get("lng_lat");
        if (ObjectUtils.isNotEmpty(lngLatObj)) {
            try {
                String bd09 = CoordinateTransformUtil.parseAndConvertToBd09(lngLatObj.toString());
                if (StringUtils.isNotBlank(bd09)) {
                    map.put("lng_lat", bd09); // 更新为第一个经纬度点
                }
            } catch (Exception e) {
                // 捕获异常并记录日志
                System.err.println("经纬度转换失败: " + e.getMessage());
            }
        }
        return map;
    }

    public List<Map<String, Object>> getArea() {
        return projectMapper.getArea();
    }

    public List<Map<String, Object>> getUseCompany() {
        return projectMapper.getUseCompany();
    }

    public List<Map<String, Object>> getBuildCompany() {
        return projectMapper.getBuildCompany();
    }
}
